﻿/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkMediaUtil.h"
#include "MkUtil/MkUtil.h"
#include <math.h>
#include <algorithm>

const Uint32 NaluStartCode = 0x01000000;
CMkMediaUtil CMkMediaUtil::m_Instance;
CMkMediaUtil::CMkMediaUtil()
{
    m_MapMediaSourceType[MkMediaSourceFile264] = "MediaSourceFile264";
    m_MapMediaSourceType[MkMediaSourceFilePs] = "MediaSourceFilePs";
    m_MapMediaSourceType[MkMediaSourceFileH265] = "MediaSourceFileH265";
    m_MapMediaSourceType[MkMediaSourceFileFlv] = "MediaSourceFileFlv";
    m_MapMediaSourceType[MkMediaSourceRtmpPlayer] = "MediaSourceRtmpPlayer";
    m_MapMediaSourceType[MkMediaSourceRtmpPublisher] = "MediaSourceRtmpPublisher";
    m_MapMediaSourceType[MkMediaSourceRtspPlayer] = "MediaSourceRtspPlayer";
    m_MapMediaSourceType[MkMediaSourceStreamPs] = "MediaSourceStreamPs";
    m_MapMediaSourceType[MkMediaSourceStreamH264] = "MediaSourceStreamH264";
    m_MapMediaSourceType[MkMediaSourceStreamH265] = "MediaSourceStreamH265";

    m_MapMediaConsumerType[MkMediaConsumeWsFlv] = "MediaConsumeWsFlv";
    m_MapMediaConsumerType[MkMediaConsumeRtmp] = "MediaConsumeRtmp";
    m_MapMediaConsumerType[MkMediaConsumeRtsp] = "MediaConsumeRtsp";
    m_MapMediaConsumerType[MkMediaConsumeGb] = "MediaConsumeGb28181";

    m_MapCodec[MkCodecUnknown] = "Unknown";
    m_MapCodec[MkCodecMjpeg] = "Mjpeg";
    m_MapCodec[MkCodecMpeg4] = "Mpeg4";
    m_MapCodec[MkCodecYuv] = "Yuv";
    m_MapCodec[MkCodecH264] = "H264";
    m_MapCodec[MkCodecH265] = "H265";
    m_MapCodec[MkCodecH263] = "H263";
    m_MapCodec[MkCodecCavs] = "Cavs";
    m_MapCodec[MkCodecAc3] = "Ac3";
    m_MapCodec[MkCodecG711u] = "PCMU";
    m_MapCodec[MkCodecG711a] = "PCMA";
    m_MapCodec[MkCodecG726] = "G726";
    m_MapCodec[MkCodecG723] = "G723";
    m_MapCodec[MkCodecAac] = "MPEG4-GENERIC";
    m_MapCodec[MkCodecPcm] = "Pcm";
    m_MapCodec[MkCodecPcmLittle] = "PcmLittle";
    m_MapCodec[MkCodecMp3] = "Mp3";
    m_MapCodec[MkCodecSpeex] = "Speex";
    m_MapCodec[MkCodecDeviceSpc] = "DeviceSpc";

    m_MapPlaycontrolType["Pause"] = MkControlPause;
    m_MapPlaycontrolType["Seek"] = MkControlSeek;
    m_MapPlaycontrolType["SetSpeed"] = MkControlSetSpeed;
    m_MapPlaycontrolType["Recovery"] = MkControlRecovery;
}
MkAudioSampleRate CMkMediaUtil::AudioSampleRateToIndex(Uint32 SampleRate)
{
    MkAudioSampleRate RateIndex = MkSampleRateFrequency;
    switch (SampleRate) {
    case 96000:
        RateIndex = MkSampleRate96000Hz;
        break;
    case 88200:
        RateIndex = MkSampleRate88200Hz;
        break;
    case 64000:
        RateIndex = MkSampleRate64000Hz;
        break;
    case 48000:
        RateIndex = MkSampleRate48000Hz;
        break;
    case 44100:
        RateIndex = MkSampleRate44100Hz;
        break;
    case 32000:
        RateIndex = MkSampleRate32000Hz;
        break;
    case 24000:
        RateIndex = MkSampleRate24000Hz;
        break;
    case 22050:
        RateIndex = MkSampleRate22050Hz;
        break;
    case 16000:
        RateIndex = MkSampleRate16000Hz;
        break;
    case 12000:
        RateIndex = MkSampleRate12000Hz;
        break;
    case 11025:
        RateIndex = MkSampleRate11025Hz;
        break;
    case 8000:
        RateIndex = MkSampleRate8000Hz;
        break;
    case 7350:
        RateIndex = MkSampleRate7350Hz;
        break;
    default:
        break;
    }
    return RateIndex;
}

Uint32 CMkMediaUtil::AudioSampleRateIndexToRate(const MkAudioSampleRate& RateIndex)
{
    Uint32 SampleRate = 0;
    switch (RateIndex) {
    case MkSampleRate96000Hz:
        SampleRate = 96000;
        break;
    case MkSampleRate88200Hz:
        SampleRate = 88200;
        break;
    case MkSampleRate64000Hz:
        SampleRate = 64000;
        break;
    case MkSampleRate48000Hz:
        SampleRate = 48000;
        break;
    case MkSampleRate44100Hz:
        SampleRate = 44100;
        break;
    case MkSampleRate32000Hz:
        SampleRate = 32000;
        break;
    case MkSampleRate24000Hz:
        SampleRate = 24000;
        break;
    case MkSampleRate22050Hz:
        SampleRate = 22050;
        break;
    case MkSampleRate16000Hz:
        SampleRate = 16000;
        break;
    case MkSampleRate12000Hz:
        SampleRate = 12000;
        break;
    case MkSampleRate11025Hz:
        SampleRate = 11025;
        break;
    case MkSampleRate8000Hz:
        SampleRate = 8000;
        break;
    case MkSampleRate7350Hz:
        SampleRate = 7350;
        break;
    default:
        break;
    }
    return SampleRate;
}

MkAudioSampleSize CMkMediaUtil::AudioSampleSizeToIndex(Uint8 SampleSize)
{
    return 16 == SampleSize ? MkSampleSize16Bits : MkSampleSize8Bits;
}

Uint8 CMkMediaUtil::AudioSampleSizeIndexToSize(const MkAudioSampleSize& SizeIndex)
{
    return  MkSampleSize16Bits == SizeIndex ? 16 : 8;
}

MkCodecType CMkMediaUtil::RtmpAudioTypeToCodec(const MkRtmpAudioType& RtmpAudioType)
{
    MkCodecType AudioType = MkCodecUnknown;
    switch (RtmpAudioType) {
    case MkAudioRtmpLinearPcmPlatformEndian:
    case MkAudioRtmpADPcm:
        AudioType = MkCodecPcm;
    case MkAudioRtmpLinearPcmLittleEndian:
        AudioType = MkCodecPcmLittle;
        break;
    case MkAudioRtmpMp3:
    case MkAudioRtmpNellymoser16Hz:
    case MkAudioRtmpNellymoser8Hz:
    case MkAudioRtmpNellymoser:
        break;
    case MkAudioRtmpG711a:
        AudioType = MkCodecG711a;
        break;
    case MkAudioRtmpG711u:
        AudioType = MkCodecG711u;
        break;
    case MkAudioRtmpReserved:
        break;
    case MkAudioRtmpAac:
        AudioType = MkCodecAac;
        break;
    case MkAudioRtmpSpeex:
        AudioType = MkCodecSpeex;
        break;
    case MkAudioRtmpMp3_8Hz:
        AudioType = MkCodecMp3;
        break;
    case MkAudioRtmpDeviceSpec:
        AudioType = MkCodecDeviceSpc;
        break;
    default:
        break;
    }
    return AudioType;
}

MkCodecType CMkMediaUtil::RtmpVideoTypeToCodec(const MkRtmpVideoType& RtmpVideoType)
{
    MkCodecType VideoType = MkCodecUnknown;
    switch (RtmpVideoType) {
    case MkVideoRtmpH263:
        VideoType = MkCodecH263;
        break;
    case MkVideoRtmpAvc:
        VideoType = MkCodecH264;
        break;
    case MkVideoRtmpHevC:
        VideoType = MkCodecH265;
        break;
    default:
        break;
    }
    return VideoType;
}

MkRtmpAudioType CMkMediaUtil::CodecToRtmpAuidoType(const MkCodecType& Codec)
{
    MkRtmpAudioType AudioType = MkAudioRtmpLinearPcmPlatformEndian;
    switch (Codec) {
    case MkCodecG711u:
        AudioType = MkAudioRtmpG711u;
        break;
    case MkCodecG711a:
        AudioType = MkAudioRtmpG711a;
        break;
    case MkCodecAac:
        AudioType = MkAudioRtmpAac;
        break;
    case MkCodecPcm:
        AudioType = MkAudioRtmpADPcm;
        break;
    case MkCodecPcmLittle:
        AudioType = MkAudioRtmpLinearPcmLittleEndian;
        break;
    case MkCodecMp3:
        AudioType = MkAudioRtmpMp3_8Hz;
        break;
    case MkCodecSpeex:
        AudioType = MkAudioRtmpSpeex;
        break;
    case MkCodecDeviceSpc:
        AudioType = MkAudioRtmpDeviceSpec;
        break;
    default:
        break;
    }
    return AudioType;
}

MkRtmpVideoType CMkMediaUtil::CodecToRtmpVideoType(const MkCodecType& Codec)
{
    MkRtmpVideoType VideoType = MkVideoRtmpUnknow;
    switch (Codec) {
    case MkCodecH263:
        VideoType = MkVideoRtmpH263;
        break;
    case MkCodecH264:
        VideoType = MkVideoRtmpAvc;
        break;
    case MkCodecH265:
        VideoType = MkVideoRtmpHevC;
        break;
    default:
        break;
    }
    return VideoType;
}

Uint32 CMkMediaUtil::Get264NaluType(const Uint8& NaluHeader, Uint8 &NaluType)
{
    NaluType = NaluHeader & 0x1F;
    return NoneError;
}

Uint32 CMkMediaUtil::Get265NaluType(const Uint8& NaluHeader, Uint8 &NaluType)
{
    NaluType = (NaluHeader & 0x7E) >> 1;
    return NoneError;
}


Uint32 CMkMediaUtil::GuessCodecType(const Uint8& NaluHeader, MkCodecType& Codec)
{
    Uint8 NaluType = 0;
    Get264NaluType(NaluHeader, NaluType);
    if (0 == NaluType) {
        Get265NaluType(NaluHeader, NaluType);
        Codec = (0 == NaluType ? MkCodecUnknown : MkCodecH265);
    } else {
        Codec = MkCodecH264;
    }
    return NoneError;
}
//
//Uint32 CMkMediaUtil::H26xSplitNaluPacket(MkEsPacket& Packet, MkVector<MkEsPacket>& VecPacket)
//{
//    Uint8 *pOffset = Packet.pData;
//    Uint8 *pBegin = Packet.pData;
//    MkEsPacket EsPacket = Packet;
//    while (pOffset < Packet.pData + Packet.nSize) {
//        if (0x00 == pOffset[0]
//            && 0x00 == pOffset[1]
//            && 0x00 == pOffset[2]
//            && 0x01 == pOffset[3]) {
//            EsPacket.pData = pBegin;
//            EsPacket.nSize = pOffset - pBegin;
//            if (MkCodecH265 == Packet.CodecType) {
//                Get265NaluType(*pBegin, EsPacket.NaluType);
//            }
//            if (MkCodecH264 == Packet.CodecType) {
//                Get264NaluType(*pBegin, EsPacket.NaluType);
//            }
//            pBegin = pOffset + 4;
//            VecPacket.push_back(EsPacket);
//        }
//        pOffset++;
//    }
//    EsPacket.pData = pBegin;
//    EsPacket.nSize = pOffset - pBegin;
//    if (MkCodecH265 == Packet.CodecType) {
//        Get265NaluType(*pBegin, EsPacket.NaluType);
//    }
//    if (MkCodecH264 == Packet.CodecType) {
//        Get264NaluType(*pBegin, EsPacket.NaluType);
//    }
//    VecPacket.push_back(EsPacket);
//    return NoneError;
//}

Uint32 CMkMediaUtil::GetNextH26xNalu(const Uint8* pBegin, const Uint8* pEnd, Uint8 const **pLastNaluEnd, Uint8 const ** pNaluHeader)
{
    Uint32 ErrorCode = InvalidParams;
    const Uint8 *pOffset = pBegin;
    while (pOffset < pEnd) {
        if (0x00 == pOffset[0]
            && 0x00 == pOffset[1]) {
            if (0x00 == pOffset[2] && 0x01 == pOffset[3]) {
                *pNaluHeader = pOffset + 4;
                *pLastNaluEnd = pOffset;
                ErrorCode = NoneError;
                break;
            } else if (0x01 == pOffset[2]) {
                *pNaluHeader = pOffset + 3;
                *pLastNaluEnd = pOffset;
                ErrorCode = NoneError;
                break;
            }
        }
        pOffset++;
    }
    return ErrorCode;
}

BOOL CMkMediaUtil::IsPacketFrame(Uint8 NaluType)
{
    return MkHevcNalIdrWRadl == NaluType || MkHevcNalIdrNLp == NaluType || MkH264NalIdrSlice == NaluType || MkH264NalSlice == NaluType;
}

Uint32 CMkMediaUtil::WriteFrameToFile(const MkString& FileName, const MkFrame& Frame)
{
    FILE *fp = fopen(FileName.c_str(), "wb");
    if (!fp) {
        return OpenFileFailed;
    }
    for (Uint32 i = 0; i < Frame.StrideY; i++) {

    }
    return NoneError;
}


Uint32 CMkMediaUtil::Ue(Uint8 *pBuff, Uint32 nLen, Uint32 &nStartBit)
{
    //计算0bit的个数
    Uint32 nZeroNum = 0;
    while (nStartBit < nLen * 8) {
        if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8))) { //&:按位与，%取余
            break;
        }
        nZeroNum++;
        nStartBit++;
    }
    nStartBit++;


    //计算结果
    Uint64 dwRet = 0;
    for (Uint32 i = 0; i < nZeroNum; i++) {
        dwRet <<= 1;
        if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8))) {
            dwRet += 1;
        }
        nStartBit++;
    }
    return ((1 << nZeroNum) - 1 + dwRet) & 0xFFFFFFFF;
}


int CMkMediaUtil::Se(Uint8 *pBuff, Uint32 nLen, Uint32 &nStartBit)
{
    int UeVal = Ue(pBuff, nLen, nStartBit);
    double k = UeVal;
    double nValue = ceil(k / 2);//ceil(2)=ceil(1.2)=cei(1.5)=2.00
    if (UeVal % 2 == 0)
        nValue = -nValue;
    return (int)nValue;
}

Uint32 CMkMediaUtil::u(Uint32 BitCount, Uint8 *buf, Uint32 &nStartBit)
{
    Uint32 dwRet = 0;
    for (Uint32 i = 0; i < BitCount; i++) {
        dwRet <<= 1;
        if (buf[nStartBit / 8] & (0x80 >> (nStartBit % 8))) {
            //dwRet += 1;
            dwRet |= 1;
        }
        nStartBit++;
    }
    return dwRet;
}

void CMkMediaUtil::DeEmulationPrevention(Uint8 *buf, unsigned int *buf_size)
{
    Uint32 i = 0, j = 0;
    Uint8 *tmp_ptr = NULL;
    Uint32 tmp_buf_size = 0;
    int val = 0;

    tmp_ptr = buf;
    tmp_buf_size = *buf_size;
    for (i = 0; i < (tmp_buf_size - 2); i++) {
        //check for 0x000003
        val = (tmp_ptr[i] ^ 0x00) + (tmp_ptr[i + 1] ^ 0x00) + (tmp_ptr[i + 2] ^ 0x03);
        if (val == 0) {
            //kick out 0x03
            for (j = i + 2; j < tmp_buf_size - 1; j++)
                tmp_ptr[j] = tmp_ptr[j + 1];

            //and so we should devrease bufsize
            (*buf_size)--;
        }
    }

    return;
}

Uint32 CMkMediaUtil::WriteCacheEsPacket(const MkEsPacket& EsPacket, MkCacheEsPacket& CacheEsPacket)
{
    CacheEsPacket.Pts = EsPacket.Pts;
    CacheEsPacket.bKeyPacket = EsPacket.bKeyPacket;
    CacheEsPacket.Dts = EsPacket.Dts;
    CacheEsPacket.CodecType = EsPacket.CodecType;
    CacheEsPacket.CacheBufferList.Append(EsPacket.BufferList);
    return NoneError;
}

Uint32 CMkMediaUtil::ReadCachePacket(const MkCacheEsPacket& CacheEsPacket, MkEsPacket& EsPacket)
{
    EsPacket.bKeyPacket = CacheEsPacket.bKeyPacket;
    EsPacket.Dts = CacheEsPacket.Dts;
    EsPacket.Pts = CacheEsPacket.Pts;
    EsPacket.CodecType = CacheEsPacket.CodecType;
    MkListStorageBuffer::const_iterator itBuffer = CacheEsPacket.CacheBufferList.GetStorageBufferList().begin();
    for (; itBuffer != CacheEsPacket.CacheBufferList.GetStorageBufferList().end(); itBuffer++) {
        EsPacket.BufferList.Append((*itBuffer)->GetBuffer(), (*itBuffer)->GetLength());
    }
    return NoneError;
}

Uint32 CMkMediaUtil::WriteCacheStream(const MkEsPacket& EsPacket, const CMkBufferList& StreamBufferList, MkCacheStreamPacket& CacheStreamPacket)
{
    CacheStreamPacket.Pts = EsPacket.Pts;
    CacheStreamPacket.bKeyPacket = EsPacket.bKeyPacket;
    CacheStreamPacket.Dts = EsPacket.Dts;
    CacheStreamPacket.CodecType = EsPacket.CodecType;
    CacheStreamPacket.CacheBufferList.Append(StreamBufferList);
    return NoneError;
}

Uint32 CMkMediaUtil::GetAacAdtsFrame(const Uint8* pInput, Uint32 nLen, const Uint8** pAdts, Uint32& AdtsLen, Uint32& nUsed)
{
    if (!pInput) {
        return InvalidParams;
    }
    const Uint8* pOffset = pInput;
    const Uint8* pEnd = pOffset + nLen;
    while (pOffset + 7 < pEnd) {
        if (0xFF == pOffset[0]
            && ((pOffset[1] & 0xf0) == 0xf0)) {
            AdtsLen |= ((pOffset[3] & 0x03) << 11);     //high 2 bit  
            AdtsLen |= pOffset[4] << 3;                //middle 8 bit  
            AdtsLen |= ((pOffset[5] & 0xe0) >> 5);        //low 3bit  
            break;
        }
        pOffset++;
    }
    if (AdtsLen + pOffset > pEnd
        || 0 == AdtsLen) {
        return NotHasEnoughBuffer;
    }
    *pAdts = pOffset;
    nUsed = AdtsLen + (pOffset - pInput);
    return NoneError;
}


Uint32 CMkMediaUtil::CreateAacAdts(const MkAacObjectType& ObjectType, const MkAudioSampleRate& SampleRate, const Uint8& nChannel, Uint32 AacRawLen, OUT Uint8* pAdts)
{
    if (!pAdts) {
        return InvalidParams;
    }
    AacRawLen += MkAacAdtsLen;
    pAdts[0] = (Uint8)0xFF;             //syncword:0xfff

    pAdts[1] = (Uint8)0xF0;             //4 bit
    pAdts[1] |= (0 << 3);   //MPEG Version:0 for MPEG-4,1 for MPEG-2   1bit
    pAdts[1] |= (0 << 1);   //Layer 0  2 bit;
    pAdts[1] |= 1;          //protection absent 1bit

    pAdts[2] = ((ObjectType - 1) & 0x03) << 6;//profile  2bit
    pAdts[2] |= (SampleRate & 0x0f) << 2; //sampling frequency index: 4bit
    pAdts[2] |= (0 << 1);       //private bit  1bit
    pAdts[2] |= (nChannel & 0x04) >> 2; // channel configuration:channels 1 bit

    pAdts[3] = (nChannel & 0x03) << 6; //channel configuration:channels 2 bit
    pAdts[3] |= (0 << 5);               //original：0                1bit
    pAdts[3] |= (0 << 4);               //home：0                    1bit
    pAdts[3] |= (0 << 3);               //copyright id bit：0        1bit
    pAdts[3] |= (0 << 2);               //copyright id start：0      1bit
    pAdts[3] |= ((AacRawLen & 0x1800) >> 11);           //frame length value   2bits

    pAdts[4] = (uint8_t)((AacRawLen & 0x7F8) >> 3);     //frame length:value    8bits

    pAdts[5] = (uint8_t)((AacRawLen & 0x7) << 5);       //frame length:value    3bits
    pAdts[5] |= 0x1F;                                 //buffer fullness:0x7ff 5bits

    pAdts[6] = (Uint8)0xFC;                                    //‭11111100‬       //buffer fullness:0x7ff 6bits
    return NoneError;
}

Uint32 CMkMediaUtil::AacAdtsParse(const Uint8* pBuf, Uint32 nLen, MkAacObjectType& ObjectType, MkAudioSampleRate& SampleRate, Uint8& nChannel)
{
    if (nLen < MkAacAdtsLen) {
        return InvalidParams;
    }
    ObjectType = (MkAacObjectType)((pBuf[2] >> 6) + 1);
    nChannel = (pBuf[2] & 0x01) | (pBuf[3] >> 6);
    SampleRate = (MkAudioSampleRate)((pBuf[2] >> 2) & 0x0f);
    //AacRawLen = (pBuf[3] & 0x03) << 11;
    //AacRawLen |= (pBuf[4]) << 3;
    //AacRawLen |= pBuf[5] >> 5; //last 3bit
    //AacRawLen -= 7;
    return NoneError;
}

Uint32 CMkMediaUtil::H264SpsParse(const Uint8 *pInput, Uint32 nLen, Uint32 &nWidth, Uint32 &nHeight, Uint32 &nFrameRate)
{
    Uint32 StartBit = 0;
    nFrameRate = 25;
    int chroma_format_idc = 1;
    if (nLen < 4) {
        return InvalidParams;
    }

    Uint8 *pSps = (Uint8 *)malloc(nLen);
    memcpy(pSps, pInput, nLen);        //重新拷贝一份数据，防止移除竞争码时对原数据造成影响
    DeEmulationPrevention(pSps, &nLen);

    int forbidden_zero_bit = u(1, pSps, StartBit);
    int nal_ref_idc = u(2, pSps, StartBit);
    int nal_unit_type = u(5, pSps, StartBit);
    if (nal_unit_type == 7) {
        int profile_idc = u(8, pSps, StartBit);
        int constraint_set0_flag = u(1, pSps, StartBit);//(buf[1] & 0x80)>>7;
        int constraint_set1_flag = u(1, pSps, StartBit);//(buf[1] & 0x40)>>6;
        int constraint_set2_flag = u(1, pSps, StartBit);//(buf[1] & 0x20)>>5;
        int constraint_set3_flag = u(1, pSps, StartBit);//(buf[1] & 0x10)>>4;
        int reserved_zero_4bits = u(4, pSps, StartBit);
        int level_idc = u(8, pSps, StartBit);

        int seq_parameter_set_id = Ue(pSps, nLen, StartBit);

        if (profile_idc == 100 || profile_idc == 110 ||
            profile_idc == 122 || profile_idc == 144) {
            chroma_format_idc = Ue(pSps, nLen, StartBit);
            if (chroma_format_idc == 3)
                int residual_colour_transform_flag = u(1, pSps, StartBit);
            int bit_depth_luma_minus8 = Ue(pSps, nLen, StartBit);
            int bit_depth_chroma_minus8 = Ue(pSps, nLen, StartBit);
            int qpprime_y_zero_transform_bypass_flag = u(1, pSps, StartBit);
            int seq_scaling_matrix_present_flag = u(1, pSps, StartBit);

            int seq_scaling_list_present_flag[8];
            if (seq_scaling_matrix_present_flag) {
                for (int i = 0; i < 8; i++) {
                    seq_scaling_list_present_flag[i] = u(1, pSps, StartBit);
                }
            }
        }
        int log2_max_frame_num_minus4 = Ue(pSps, nLen, StartBit);
        int pic_order_cnt_type = Ue(pSps, nLen, StartBit);
        if (pic_order_cnt_type == 0) {
            int log2_max_pic_order_cnt_lsb_minus4 = Ue(pSps, nLen, StartBit);
        } else if (pic_order_cnt_type == 1) {
            int delta_pic_order_always_zero_flag = u(1, pSps, StartBit);
            int offset_for_non_ref_pic = Se(pSps, nLen, StartBit);
            int offset_for_top_to_bottom_field = Se(pSps, nLen, StartBit);
            int num_ref_frames_in_pic_order_cnt_cycle = Ue(pSps, nLen, StartBit);

            int *offset_for_ref_frame = new int[num_ref_frames_in_pic_order_cnt_cycle];
            for (int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)
                offset_for_ref_frame[i] = Se(pSps, nLen, StartBit);
            delete[] offset_for_ref_frame;
        }
        int num_ref_frames = Ue(pSps, nLen, StartBit);
        int gaps_in_frame_num_value_allowed_flag = u(1, pSps, StartBit);
        int pic_width_in_mbs_minus1 = Ue(pSps, nLen, StartBit);
        int pic_height_in_map_units_minus1 = Ue(pSps, nLen, StartBit);

        int frame_mbs_only_flag = u(1, pSps, StartBit);
        if (!frame_mbs_only_flag)
            int mb_adaptive_frame_field_flag = u(1, pSps, StartBit);

        nWidth = (pic_width_in_mbs_minus1 + 1) * 16;
        nHeight = (2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16;

        int direct_8x8_inference_flag = u(1, pSps, StartBit);
        int frame_cropping_flag = u(1, pSps, StartBit);
        if (frame_cropping_flag) {
            int frame_crop_left_offset = Ue(pSps, nLen, StartBit);
            int frame_crop_right_offset = Ue(pSps, nLen, StartBit);
            int frame_crop_top_offset = Ue(pSps, nLen, StartBit);
            int frame_crop_bottom_offset = Ue(pSps, nLen, StartBit);
            int crop_unit_x = 1;
            int crop_unit_y = 2 - frame_mbs_only_flag;      //monochrome or 4:4:4
            if (chroma_format_idc == 1) {   //4:2:0
                crop_unit_x = 2;
                crop_unit_y = 2 * (2 - frame_mbs_only_flag);
            } else if (chroma_format_idc == 2) {  //4:2:2
                crop_unit_x = 2;
                crop_unit_y = 2 - frame_mbs_only_flag;
            }

            nWidth -= crop_unit_x * (frame_crop_left_offset + frame_crop_right_offset);
            nHeight -= crop_unit_y * (frame_crop_top_offset + frame_crop_bottom_offset);
        }
        int vui_parameter_present_flag = u(1, pSps, StartBit);
        if (vui_parameter_present_flag) {
            int aspect_ratio_info_present_flag = u(1, pSps, StartBit);
            if (aspect_ratio_info_present_flag) {
                int aspect_ratio_idc = u(8, pSps, StartBit);
                if (aspect_ratio_idc == 255) {
                    int sar_width = u(16, pSps, StartBit);
                    int sar_height = u(16, pSps, StartBit);
                }
            }
            int overscan_info_present_flag = u(1, pSps, StartBit);
            if (overscan_info_present_flag)
                int overscan_appropriate_flagu = u(1, pSps, StartBit);
            int video_signal_type_present_flag = u(1, pSps, StartBit);
            if (video_signal_type_present_flag) {
                int video_format = u(3, pSps, StartBit);
                int video_full_range_flag = u(1, pSps, StartBit);
                int colour_description_present_flag = u(1, pSps, StartBit);
                if (colour_description_present_flag) {
                    int colour_primaries = u(8, pSps, StartBit);
                    int transfer_characteristics = u(8, pSps, StartBit);
                    int matrix_coefficients = u(8, pSps, StartBit);
                }
            }
            int chroma_loc_info_present_flag = u(1, pSps, StartBit);
            if (chroma_loc_info_present_flag) {
                int chroma_sample_loc_type_top_field = Ue(pSps, nLen, StartBit);
                int chroma_sample_loc_type_bottom_field = Ue(pSps, nLen, StartBit);
            }
            int timing_info_present_flag = u(1, pSps, StartBit);
            if (timing_info_present_flag) {
                int num_units_in_tick = u(32, pSps, StartBit);
                int time_scale = u(32, pSps, StartBit);
                int fixed_frame_rate_flag = u(1, pSps, StartBit);
                nFrameRate = time_scale / num_units_in_tick;
                nFrameRate = nFrameRate / 2;
                //if (fixed_frame_rate_flag) {
                //     nFrameRate = nFrameRate / 2;
                //}
            }
        }
        free(pSps);
        return NoneError;
    }
    return InvalidParams;
}

#define HevcMaxSubLayers 7
#define HevcMaxSpsCount  16
#define HevcMaxDpbSize   16
//reference resources  ffmpeg hevc.ps.c  ff_hevc_parse_sps
Uint32 CMkMediaUtil::H265SpsParse(const Uint8 *pInput, Uint32 nLen, Uint32 &nWidth, Uint32 &nHeight)
{
    if (nLen < 20) {
        return InvalidParams;
    }
    Uint8 *pSps = (Uint8 *)malloc(nLen);
    memcpy(pSps, pInput, nLen);        //重新拷贝一份数据，防止移除竞争码时对原数据造成影响
    DeEmulationPrevention(pSps, &nLen);

    Uint32 StartBit = 0;
    int sps_video_parameter_set_id = u(4, pSps, StartBit);
    int sps_max_sub_layers_minus1 = u(3, pSps, StartBit);
    if (sps_max_sub_layers_minus1 > HevcMaxSubLayers) {
        MkFree(pSps);
        return false;
    }
    int sps_temporal_id_nesting_flag = u(1, pSps, StartBit);
    int general_profile_space = u(2, pSps, StartBit);
    int general_tier_flag = u(1, pSps, StartBit);
    int general_profile_idc = u(5, pSps, StartBit);
    int general_profile_compatibility_flag = u(32, pSps, StartBit);  //general_profile_compatibility_flag[32] 
    int general_progressive_source_flag = u(1, pSps, StartBit);//
    int general_interlaced_source_flag = u(1, pSps, StartBit);//
    int general_non_packed_constraint_flag = u(1, pSps, StartBit);//
    int general_frame_only_constraint_flag = u(1, pSps, StartBit);//
    int general_reserved_zero_44bits = u(44, pSps, StartBit);//
    int general_level_idc = u(8, pSps, StartBit);

    Uint8 sub_layer_profile_present_flag[6] = { 0 };
    Uint8 sub_layer_level_present_flag[6] = { 0 };
    for (int i = 0; i < sps_max_sub_layers_minus1; i++) {
        sub_layer_profile_present_flag[i] = u(1, pSps, StartBit);
        sub_layer_level_present_flag[i] = u(1, pSps, StartBit);
    }
    if (sps_max_sub_layers_minus1 > 0) {
        for (int i = sps_max_sub_layers_minus1; i < 8; i++) {
            Uint8 reserved_zero_2bits = u(2, pSps, StartBit);
        }
    }
    for (int i = 0; i < sps_max_sub_layers_minus1; i++) {
        if (sub_layer_profile_present_flag[i]) {
            int sub_layer_profile_space = u(2, pSps, StartBit);
            int sub_layer_tier_flag = u(1, pSps, StartBit);
            int sub_layer_profile_idc = u(5, pSps, StartBit);
            int sub_layer_profile_compatibility_flag = u(32, pSps, StartBit);
            int sub_layer_progressive_source_flag = u(1, pSps, StartBit);
            int sub_layer_interlaced_source_flag = u(1, pSps, StartBit);
            int sub_layer_non_packed_constraint_flag = u(1, pSps, StartBit);
            int sub_layer_frame_only_constraint_flag = u(1, pSps, StartBit);
            int sub_layer_reserved_zero_44bits = u(44, pSps, StartBit);
        }
        if (sub_layer_level_present_flag[i]) {
            int sub_layer_level_idc = u(8, pSps, StartBit);// sub_layer_level_idc[i]
        }
    }

    Uint32 sps_seq_parameter_set_id = Ue(pSps, nLen, StartBit);
    if (sps_seq_parameter_set_id > HevcMaxSpsCount) {
        MkFree(pSps);
        return false;
    }
    Uint32 chroma_format_idc = Ue(pSps, nLen, StartBit);
    if (sps_seq_parameter_set_id > 3) {
        MkFree(pSps);
        return false;
    }
    if (chroma_format_idc == 3) {
        int separate_colour_plane_flag = u(1, pSps, StartBit);
        if (separate_colour_plane_flag) {
            chroma_format_idc = 0;
        }
    }

    nWidth = Ue(pSps, nLen, StartBit); // pic_width_in_luma_samples
    nHeight = Ue(pSps, nLen, StartBit); // pic_height_in_luma_samples
    int conformance_window_flag = u(1, pSps, StartBit);
    if (conformance_window_flag) {
        int conf_win_left_offset = Ue(pSps, nLen, StartBit);
        int conf_win_right_offset = Ue(pSps, nLen, StartBit);
        int conf_win_top_offset = Ue(pSps, nLen, StartBit);
        int conf_win_bottom_offset = Ue(pSps, nLen, StartBit);
        nWidth -= (conf_win_left_offset + conf_win_right_offset);
        nHeight -= conf_win_top_offset + conf_win_bottom_offset;
    }

    Uint32 bit_depth_luma_minus8 = Ue(pSps, nLen, StartBit) + 8;
    Uint32 bit_depth_chroma_minus8 = Ue(pSps, nLen, StartBit) + 8;
    if (chroma_format_idc && bit_depth_luma_minus8 != bit_depth_chroma_minus8) {
        free(pSps);
        return InvalidParams;
    }
    free(pSps);
    return NoneError;
    Uint32 log2_max_poc_lsb = Ue(pSps, nLen, StartBit) + 4;
    if (log2_max_poc_lsb > 16) {
        free(pSps);
        return InvalidParams;
    }
    Uint32 sublayer_ordering_info = u(1, pSps, StartBit);
    Uint32 start = sublayer_ordering_info ? 0 : sps_max_sub_layers_minus1 - 1;
    for (int i = start; i < sps_max_sub_layers_minus1; i++) {
        Uint32 max_dec_pic_buffering = Ue(pSps, nLen, StartBit) + 1;
        Uint32 num_reorder_pics = Ue(pSps, nLen, StartBit);
        Uint32 max_latency_increase = Ue(pSps, nLen, StartBit);
        if (max_dec_pic_buffering > HevcMaxDpbSize) {
            free(pSps);
            return InvalidParams;
        }
    }
    Uint32 log2_min_cb_size = Ue(pSps, nLen, StartBit) + 3;
    Uint32 log2_diff_max_min_coding_block_size = Ue(pSps, nLen, StartBit);
    Uint32 log2_min_tb_size = Ue(pSps, nLen, StartBit) + 2;
    Uint32 log2_diff_max_min_transform_block_size = Ue(pSps, nLen, StartBit);
    Uint32 max_transform_hierarchy_depth_inter = Ue(pSps, nLen, StartBit);
    Uint32 max_transform_hierarchy_depth_intra = Ue(pSps, nLen, StartBit);
    Uint32 scaling_list_enable_flag = u(1, pSps, StartBit);
    Uint32 amp_enabled_flag = u(1, pSps, StartBit);
    Uint32 sao_enabled = u(1, pSps, StartBit);
    Uint32 pcm_enabled_flag = u(1, pSps, StartBit);
    if (pcm_enabled_flag) {
        Uint32 bit_depth = u(4, pSps, StartBit) + 1;
        Uint32 bit_depth_chroma = u(4, pSps, StartBit) + 1;
        Uint32 log2_min_pcm_cb_size = Ue(pSps, nLen, StartBit) + 3;
        Uint32 log2_max_pcm_cb_size = log2_min_pcm_cb_size + Ue(pSps, nLen, StartBit);
        Uint32 loop_filter_disable_flag = u(1, pSps, StartBit);
    }
    Uint32  nb_st_rps = Ue(pSps, nLen, StartBit);
    if (nb_st_rps > 64) {
        free(pSps);
        return InvalidParams;
    }
    for (Uint32 i = 0; i < nb_st_rps; i++) {
        Uint8 rps_predict = u(1, pSps, StartBit);
        if (rps_predict) {
            Uint8 delta_rps_sign = u(1, pSps, StartBit);
            Uint32 abs_delta_rps = Ue(pSps, nLen, StartBit) + 1;
        } else {
            Uint32 num_negative_pics = Ue(pSps, nLen, StartBit);
            Uint32 nb_positive_pics = Ue(pSps, nLen, StartBit);
            for (Uint32 i = 0; i < num_negative_pics; i++) {
                Uint32 delta_poc = Ue(pSps, nLen, StartBit);
                Uint8 used = u(1, pSps, StartBit);
            }
            for (Uint32 i = 0; i < nb_positive_pics; i++) {
                Uint32 delta_poc = Ue(pSps, nLen, StartBit);
                Uint8 used = u(1, pSps, StartBit);
            }
        }
    }
    Uint8 long_term_ref_pics_present_flag = u(1, pSps, StartBit);
    if (long_term_ref_pics_present_flag) {
        Uint32 num_long_term_ref_pics_sps = Ue(pSps, nLen, StartBit);
        for (Uint32 i = 0; i < num_long_term_ref_pics_sps; i++) {
            Uint8 lt_ref_pic_poc_lsb_sps = u(log2_max_poc_lsb, pSps, StartBit);
            Uint8 used_by_curr_pic_lt_sps_flag = u(1, pSps, StartBit);
        }
    }
    Uint8 sps_temporal_mvp_enabled_flag = u(1, pSps, StartBit);
    Uint8 sps_strong_intra_smoothing_enable_flag = u(1, pSps, StartBit);
    Uint8 vui_present = u(1, pSps, StartBit);
    if (vui_present) {
        Uint8 sar_present = u(1, pSps, StartBit);
        if (sar_present) {
            Uint8 sar_idx = u(8, pSps, StartBit);
            if (255 == sar_idx) {
                Uint32 num = u(16, pSps, StartBit);
                Uint32 den = u(16, pSps, StartBit);
            }
        }
    }
    Uint8 overscan_info_present_flag = u(1, pSps, StartBit);
    if (overscan_info_present_flag) {
        Uint8 overscan_appropriate_flag = u(1, pSps, StartBit);
    }
    Uint8 video_signal_type_present_flag = u(1, pSps, StartBit);
    if (video_signal_type_present_flag) {
        Uint8 video_format = u(3, pSps, StartBit);
        Uint8 video_full_range_flag = u(1, pSps, StartBit);
        Uint8 colour_description_present_flag = u(1, pSps, StartBit);
        if (colour_description_present_flag) {
            Uint8 colour_primaries = u(8, pSps, StartBit);
            Uint8 transfer_characteristic = u(8, pSps, StartBit);
            Uint8 matrix_coeffs = u(8, pSps, StartBit);
        }
    }
    Uint8 chroma_loc_info_present_flag = u(1, pSps, StartBit);
    if (chroma_loc_info_present_flag) {
        Uint32 chroma_sample_loc_type_top_field = Ue(pSps, nLen, StartBit);
        Uint32 chroma_sample_loc_type_bottom_field = Ue(pSps, nLen, StartBit);
    }
    Uint8 neutra_chroma_indication_flag = u(1, pSps, StartBit);
    Uint8 field_seq_flag = u(1, pSps, StartBit);
    Uint8 frame_field_info_present_flag = u(1, pSps, StartBit);
    return NoneError;
}

//reference resources  ffmpeg hevc.ps.c  ff_hevc_decode_nal_vps
Uint32 CMkMediaUtil::H265VpsParse(const Uint8 *pInput, Uint32 nLen, Uint32 &nFrameRate)
{
    Uint8 *pVps = (Uint8 *)malloc(nLen);
    memcpy(pVps, pInput, nLen);
    DeEmulationPrevention(pVps, &nLen);
    Uint32 StartBit = 0;
    int i = 0;
    Uint8 vps_video_parameter_set_id = u(4, pVps, StartBit);
    Uint8 vps_reserved_three_2bits = u(2, pVps, StartBit);
    Uint8 vps_max_layers_minus1 = u(6, pVps, StartBit) + 1;
    Uint8 vps_max_sub_layers_minus1 = u(3, pVps, StartBit) + 1;
    Uint8 vps_temporal_id_nesting_flag = u(1, pVps, StartBit);
    Uint32 vps_reserved_ffff_16bits = u(16, pVps, StartBit);

    StartBit += 84;
    /*Uint8 profile_space = u(2, pVps, StartBit);
    Uint8 tier_flag = u(1, pVps, StartBit);
    Uint8 profile_idc = u(5, pVps, StartBit);
    for (i=0;i<32;i++)
    {
        Uint8 profile_compatibility_flag = u(1, pVps, StartBit);
        if (profile_idc==0 && i>0 && profile_compatibility_flag)
        {
            profile_idc = i;
        }
    }
    Uint8 progressive_source_flag = u(1, pVps, StartBit);
    Uint8 interlaced_source_flag = u(1, pVps, StartBit);
    Uint8 non_packed_constraint_flag = u(1, pVps, StartBit);
    Uint8 frame_only_constraint_flag = u(1, pVps, StartBit);
    if (4 <= profile_idc&& profile_idc <=10)
    {
        Uint8 max_12bit_constraint_flag = u(1, pVps, StartBit);
        Uint8 max_10bit_constraint_flag = u(1, pVps, StartBit);
        Uint8 max_8bit_constraint_flag = u(1, pVps, StartBit);
        Uint8 max_422chroma_constraint_flag = u(1, pVps, StartBit);
        Uint8 max_420chroma_constraint_flag = u(1, pVps, StartBit);
        Uint8 max_monochrome_constraint_flag = u(1, pVps, StartBit);
        Uint8 intra_constraint_flag = u(1, pVps, StartBit);
        Uint8 one_picture_only_constraint_flag = u(1, pVps, StartBit);
        Uint8 lower_bit_rate_constraint_flag = u(1, pVps, StartBit);
        if (5 == profile_idc || 9 == profile_idc || 10 ==profile_idc)
        {
           Uint8 max_14bit_constraint_flag = u(1, pVps, StartBit);
           u(1, pVps, StartBit);
           u(32, pVps, StartBit);
        } else {
            u(2, pVps, StartBit);
            u(32, pVps, StartBit);
        }
    }else if (2==profile_idc)
    {
        u(7, pVps, StartBit);
        Uint8 one_picture_only_constraint_flag =  u(1, pVps, StartBit);
        u(3, pVps, StartBit);
        u(32, pVps, StartBit);
    } else {
        u(11, pVps, StartBit);
        u(32, pVps, StartBit);
    }
     u(1, pVps, StartBit);*/

    Uint8 sub_layer_profile_present_flag[Len16] = { 0 };
    Uint8 sub_layer_level_present_flag[Len16] = { 0 };
    Uint8 level_idc = u(8, pVps, StartBit);
    for (i = 0; i < vps_max_sub_layers_minus1 - 1; i++) {
        sub_layer_profile_present_flag[i] = u(1, pVps, StartBit);
        sub_layer_level_present_flag[i] = u(1, pVps, StartBit);
    }
    if (vps_max_sub_layers_minus1 - 1 > 0) {
        for (i = vps_max_sub_layers_minus1 - 1; i < 0; i++) {
            u(2, pVps, StartBit);
        }
    }
    for (i = 0; i < vps_max_sub_layers_minus1 - 1; i++) {
        if (sub_layer_profile_present_flag[i]) {
            StartBit += 84;
        }
        if (sub_layer_level_present_flag[i]) {
            StartBit += 8;
        }
    }
    Uint32 vps_max_dec_pic_buffering[Len16] = { 0 };
    Uint32 vps_num_reorder_pics[Len16] = { 0 };
    Uint32 vps_max_latency_increase[Len16] = { 0 };
    Uint8 vps_sub_layer_ordering_info_present_flag = u(1, pVps, StartBit);
    for (i = 0; i < vps_max_layers_minus1; i++) {
        vps_max_dec_pic_buffering[i] = u(32, pVps, StartBit) + 1;
        vps_num_reorder_pics[i] = u(32, pVps, StartBit);
        vps_max_latency_increase[i] = u(32, pVps, StartBit);
    }
    Uint8 vps_max_layer_id = u(6, pVps, StartBit);
    Uint32 vps_num_layer_sets = u(32, pVps, StartBit) + 1;
    StartBit += vps_max_layer_id * vps_num_layer_sets;

    Uint8 vps_timing_info_present_flag = u(1, pVps, StartBit);
    if (vps_timing_info_present_flag) {
        Uint32 vps_num_units_in_tick = u(32, pVps, StartBit);
        Uint32 vps_time_scale = u(32, pVps, StartBit);
        Uint8 vps_poc_proportional_to_timing_flag = u(1, pVps, StartBit);
    }
    MkFree(pVps);
    return NoneError;
}

CMkVideoParam::CMkVideoParam()
    : m_Codec(MkCodecUnknown)
    , m_Width(0)
    , m_Height(0)
    , m_FrameRate(0)
    , m_BitRate(0)
    , m_CurTimeStamp(0)
{

}

CMkVideoParam::CMkVideoParam(const MkCodecType& Codec, const Uint32& Width, const Uint32& Height, const Uint32& FrameRate, const Uint32& BitRate)
    : m_Codec(Codec)
    , m_Width(Width)
    , m_Height(Height)
    , m_FrameRate(FrameRate)
    , m_BitRate(BitRate)
    , m_CurTimeStamp(0)
{

}

CMkAudioParam::CMkAudioParam()
    : m_Codec(MkCodecUnknown)
    , m_BitRate(0)
    , m_SampleRate(MkSampleRate8000Hz)
    , m_SampleSize(MkSampleSize16Bits)
    , m_bStereo(FALSE)
    , m_Channel(0)
    , m_ObjectType(MkAacObjectNull)
    , m_CurTimeStamp(0)
{

}

CMkAudioParam::CMkAudioParam(const MkCodecType& Codec, const Uint32& BitRate, const MkAudioSampleRate& SampleRate, const MkAudioSampleSize& SampleSize, const BOOL& bStereo, const Uint8& Channel)
    : m_Codec(Codec)
    , m_BitRate(BitRate)
    , m_SampleRate(SampleRate)
    , m_SampleSize(SampleSize)
    , m_bStereo(bStereo)
    , m_Channel(Channel)
    , m_CurTimeStamp(0)
{

}

const MkString& CMkMediaUtil::GetStringMediaSourceType(const MkMediaSourceType& SourceType) const
{
    MkUnorderedMap<Uint32, MkString>::const_iterator  it = m_MapMediaSourceType.find(SourceType);
    if (it != m_MapMediaSourceType.end()) {
        return it->second;
    }
    return CMkUtil::GetEmptyString();
}

const MkString& CMkMediaUtil::GetStringMediaConsumerType(const MkMediaConsumeType& ConsumerType) const
{
    MkUnorderedMap<Uint32, MkString>::const_iterator  it = m_MapMediaConsumerType.find(ConsumerType);
    if (it != m_MapMediaConsumerType.end()) {
        return it->second;
    }
    return CMkUtil::GetEmptyString();
}

const MkString& CMkMediaUtil::GetStringCodec(const MkCodecType& Codec) const
{
    MkUnorderedMap<Uint32, MkString>::const_iterator  it = m_MapCodec.find(Codec);
    if (it != m_MapCodec.end()) {
        return it->second;
    }
    return CMkUtil::GetEmptyString();
}

MkCodecType CMkMediaUtil::GetCodec(const MkString& strCodec) const
{
    MkString TmpCodeType = strCodec;
    std::transform(TmpCodeType.begin(), TmpCodeType.end(), TmpCodeType.begin(), ::toupper);
    MkUnorderedMap<Uint32, MkString>::const_iterator  it = m_MapCodec.begin();
    for (; it != m_MapCodec.end(); it++) {
        if (it->second == TmpCodeType) {
            return (MkCodecType)it->first;
        }
    }
    return MkCodecUnknown;
}

MkPlaybackControlType CMkMediaUtil::GetPlaybackControlType(const MkString& StringControlType) const
{
    MkUnorderedMap<MkString, MkPlaybackControlType>::const_iterator it = m_MapPlaycontrolType.find(StringControlType);
    if (it != m_MapPlaycontrolType.end()) {
        return it->second;
    }
    return MkControlUnknown;
}

Uint64 CMkMediaUtil::GetAverageSpeed(Uint64 TatolBytes, const CMkTime& StartTime, const CMkTime& EndTime/* = NowMkTime*/)
{
    Uint64 uRet = TatolBytes;
    int UseSec = EndTime.OffsetSec(StartTime);
    if (UseSec > 0) {
        uRet = TatolBytes / UseSec;
    }
    return uRet;
}